import os
import cv2
import numpy as np
import hyperlpr3 as lpr3
from PIL import Image, ImageDraw, ImageFont
from flask import Flask, request, jsonify, send_file
from flask_cors import CORS
import tempfile

app = Flask(__name__)
CORS(app)  # 启用CORS支持跨域请求

# 实例化识别对象，在应用启动时创建以提高性能
catcher = lpr3.LicensePlateCatcher(detect_level=lpr3.DETECT_LEVEL_HIGH)


def process_image(image_array):
    """处理图像并识别车牌"""
    results = catcher(image_array)
    plate_numbers = []

    if len(results) == 0:
        return image_array, plate_numbers, "未识别到任何车牌"

    for result in results:
        if len(result) == 4:
            code, confidence, _, bbox = result
            plate_numbers.append({
                "plate_number": code,
                "confidence": float(confidence)
            })

            if isinstance(bbox, list) and len(bbox) == 4:
                # 处理bbox数据
                x1, y1, x2, y2 = bbox
                points = [(x1, y1), (x2, y1), (x2, y2), (x1, y2)]

                # 使用OpenCV绘制多边形
                pts = np.array(points, np.int32)
                pts = pts.reshape((-1, 1, 2))
                cv2.polylines(image_array, [pts], isClosed=True, color=(0, 0, 255), thickness=2)

                # 将中文车牌号码通过PIL绘制到图像上
                result_image_pil = Image.fromarray(cv2.cvtColor(image_array, cv2.COLOR_BGR2RGB))
                draw = ImageDraw.Draw(result_image_pil)

                # 尝试加载中文字体
                try:
                    font_path = "D:/字体/platech.ttf"  # 根据系统安装字体情况调整路径
                    font = ImageFont.truetype(font_path, 36)
                except IOError:
                    # 使用默认字体
                    font = ImageFont.load_default()

                # 获取文本大小
                min_y = min(point[1] for point in points)
                text_bbox = draw.textbbox((points[0][0], min_y - 36), code, font=font)

                # 在车牌上方写上识别出的车牌号码，带背景
                draw.rectangle(text_bbox, fill="white")
                draw.text((points[0][0], min_y - 36), code, fill=(0, 0, 255), font=font)

                # 将图像转换回NumPy数组
                image_array = cv2.cvtColor(np.array(result_image_pil), cv2.COLOR_RGB2BGR)

    return image_array, plate_numbers, "成功识别"


@app.route('/api/recognize', methods=['POST'])
def recognize_license_plate():
    """识别车牌API接口"""
    try:
        # 检查请求中是否有文件
        if 'image' not in request.files:
            return jsonify({"error": "未上传图像文件"}), 400

        file = request.files['image']

        # 检查文件是否有文件名
        if file.filename == '':
            return jsonify({"error": "空文件名"}), 400

        # 读取图像
        img = Image.open(file.stream).convert('RGB')
        image_array = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)

        # 处理图像
        processed_image, plate_numbers, message = process_image(image_array)

        # 将处理后的图像保存到临时文件
        with tempfile.NamedTemporaryFile(delete=False, suffix='.jpg') as tmp:
            temp_path = tmp.name
            result_image = cv2.cvtColor(processed_image, cv2.COLOR_BGR2RGB)
            Image.fromarray(result_image).save(temp_path)

        # 准备响应
        response = {
            "status": "success",
            "message": message,
            "plates": plate_numbers,
            "image_url": f"{request.host_url}api/image/{os.path.basename(temp_path)}"
        }

        return jsonify(response)

    except Exception as e:
        return jsonify({
            "status": "error",
            "message": f"识别过程中发生错误: {str(e)}"
        }), 500


@app.route('/api/image/<path:filename>')
def serve_image(filename):
    """提供处理后的图像"""
    return send_file(os.path.join(tempfile.gettempdir(), filename), mimetype='image/jpeg')


if __name__ == '__main__':
    app.run(debug=True)